/* Created by Darren Otgaar on 2016/03/22. http://www.github.com/otgaard/zap */
#include "gl_api.hpp"

using namespace zap::engine;

bool zap::engine::_gl_error_log(const char* file, int line) {
    using namespace gl;

    GLenum err = glGetError();
    if(err != GL_NO_ERROR) {
        std::string error;
        switch(err) {
            case GL_INVALID_OPERATION: error = "GL_INVALID_OPERATION"; break;
            case GL_INVALID_ENUM: error = "GL_INVALID_ENUM"; break;
            case GL_INVALID_VALUE: error = "GL_INVALID_VALUE"; break;
            case GL_OUT_OF_MEMORY: error = "GL_OUT_OF_MEMORY"; break;
            case GL_INVALID_FRAMEBUFFER_OPERATION: error = "GL_INVALID_FRAMEBUFFER_OPERATION"; break;
        }
        LOG_ERR("OpenGL Error:", error, "in", file, "@", line);
        return true;
    }

    return false;
}

bool zap::engine::_gl_error_check() {
    return gl::glGetError() != GL_NO_ERROR;
}

void gl::bind_buffer_base(buffer_type type, int location, uint32_t bo) {
    glBindBufferBase(zap::engine::gl::gl_type(type), location, bo);
}

#include "engine.hpp"

bool zap::engine::init() {
    using namespace gl;

    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if(err != GLEW_OK) {
        LOG("GLEW failed to initialise: ", glewGetErrorString(err));
        return false;
    }

#ifdef LOGGING_ENABLED
    LOG("Suppressing error generated by GLEW", glGetError());
#else
    glGetError();
#endif
    return true;
}

uint32_t zap::engine::gl_internal_format(zap::engine::pixel_format pf, zap::engine::pixel_datatype dt) {
    using namespace zap::engine; using namespace gl;
    if(dt == pixel_datatype::PD_UNSIGNED_BYTE) return gl_type(pf);
    else if(dt == pixel_datatype::PD_UNSIGNED_INT_24_8) return GL_DEPTH24_STENCIL8;
    else if(dt == pixel_datatype::PD_UNSIGNED_BYTE_3_3_2) return gl_type(pf);
    else if(dt == pixel_datatype::PD_DN_UNSIGNED_BYTE) {
        if(pf == pixel_format::PF_RED_INTEGER)  return GL_R8UI;
        if(pf == pixel_format::PF_RG_INTEGER)   return GL_RG8UI;
        if(pf == pixel_format::PF_RGB_INTEGER)  return GL_RGB8UI;
        if(pf == pixel_format::PF_RGBA_INTEGER) return GL_RGBA8UI;
    }
    else if(dt == pixel_datatype::PD_FLOAT) {
        if(pf == pixel_format::PF_RED)  return GL_R32F;
        if(pf == pixel_format::PF_RG)   return GL_RG32F;
        if(pf == pixel_format::PF_RGB)  return GL_RGB32F;
        if(pf == pixel_format::PF_RGBA) return GL_RGBA32F;
        if(pf == pixel_format::PF_DEPTH_COMPONENT) return GL_DEPTH_COMPONENT32F;
    }
    return GL_NONE;
}